load("@com_github_johnynek_bazel_jar_jar//:jar_jar.bzl", "jar_jar")
load("@fmeum_rules_jni//jni:defs.bzl", "java_jni_library")
load("//bazel:compat.bzl", "SKIP_ON_WINDOWS")
load("//bazel:jar.bzl", "strip_jar")

# The transitive dependencies of this target will be appended to the search path
# of the bootstrap class loader. They will be visible to all classes - care must
# be taken to shade everything and generally keep this target as small as
# possible.
java_binary(
    name = "jazzer_bootstrap_unshaded",
    create_executable = False,
    runtime_deps = [":jazzer_bootstrap_lib"],
)

java_library(
    name = "jazzer_bootstrap_lib",
    visibility = ["//src/main/java/com/code_intelligence/jazzer:__pkg__"],
    runtime_deps = [
        ":runtime",
        "//sanitizers",
    ],
)

# These classes with public Bazel visibility are contained in jazzer_bootstrap.jar
# and will thus be available on the bootstrap class path. This target can be
# passed to the `deploy_env` attribute of the Jazzer `java_binary` to ensure that
# it doesn't bundle in these classes.
java_binary(
    name = "jazzer_bootstrap_env",
    create_executable = False,
    visibility = [
        "//selffuzz:__pkg__",
        "//src/main/java/com/code_intelligence/jazzer:__pkg__",
    ],
    runtime_deps = [
        "//src/main/java/com/code_intelligence/jazzer/api:hooks",
        "//src/main/java/com/code_intelligence/jazzer/utils:unsafe_provider",
    ],
)

jar_jar(
    name = "jazzer_bootstrap_unstripped",
    input_jar = ":jazzer_bootstrap_unshaded_deploy.jar",
    rules = "bootstrap_shade_rules",
)

strip_jar(
    name = "jazzer_bootstrap",
    out = "jazzer_bootstrap.jar",
    jar = ":jazzer_bootstrap_unstripped",
    paths_to_keep = [
        "com/code_intelligence/jazzer/**",
        "jaz/**",
        "META-INF/MANIFEST.MF",
    ],
    visibility = [
        "//src/main/java/com/code_intelligence/jazzer/agent:__pkg__",
        "//src/main/java/com/code_intelligence/jazzer/android:__pkg__",
    ],
)

sh_test(
    name = "jazzer_bootstrap_shading_test",
    srcs = ["verify_shading.sh"],
    args = [
        "$(rootpath jazzer_bootstrap.jar)",
        "$(JAVABASE)",
    ],
    data = [
        "jazzer_bootstrap.jar",
        "@bazel_tools//tools/jdk:current_java_runtime",
    ],
    tags = [
        # Coverage instrumentation necessarily adds files to the jar that we
        # wouldn't want to release and thus causes this test to fail.
        "no-coverage",
    ],
    target_compatible_with = SKIP_ON_WINDOWS,
    toolchains = [
        "@bazel_tools//tools/jdk:current_java_runtime",
    ],
)

# At runtime, the AgentInstaller appends jazzer_bootstrap.jar to the bootstrap
# class loader's search path - these classes must not be available on the
# regular classpath. Since dependents should not have to resort to reflection to
# access these classes they know will be there at runtime, this compile-time
# only dependency can be used as a replacement.
java_library(
    name = "jazzer_bootstrap_compile_only",
    neverlink = True,
    visibility = [
        "//src/main/java/com/code_intelligence/jazzer/autofuzz:__pkg__",
        "//src/main/java/com/code_intelligence/jazzer/driver:__pkg__",
        "//src/main/java/com/code_intelligence/jazzer/instrumentor:__pkg__",
    ],
    exports = [
        ":fuzz_target_runner_natives",
        ":runtime",
    ],
)

# The following targets must only be referenced directly by tests or native implementations.

java_jni_library(
    name = "coverage_map",
    srcs = ["CoverageMap.java"],
    native_libs = select({
        "@platforms//os:android": ["//src/main/native/com/code_intelligence/jazzer/driver:jazzer_driver"],
        "//conditions:default": [],
    }),
    visibility = [
        "//src/jmh/java/com/code_intelligence/jazzer/instrumentor:__pkg__",
        "//src/main/native/com/code_intelligence/jazzer/driver:__pkg__",
        "//src/test:__subpackages__",
    ],
    deps = [
        "//src/main/java/com/code_intelligence/jazzer/runtime:constants",
        "//src/main/java/com/code_intelligence/jazzer/utils:unsafe_provider",
    ],
)

java_jni_library(
    name = "trace_data_flow_native_callbacks",
    srcs = ["TraceDataFlowNativeCallbacks.java"],
    visibility = [
        "//src/main/native/com/code_intelligence/jazzer/driver:__pkg__",
    ],
    deps = ["@org_ow2_asm_asm//jar"],
)

java_jni_library(
    name = "fuzz_target_runner_natives",
    srcs = ["FuzzTargetRunnerNatives.java"],
    visibility = ["//src/main/native/com/code_intelligence/jazzer/driver:__pkg__"],
    deps = [
        ":constants",
    ],
)

java_jni_library(
    name = "mutator",
    srcs = ["Mutator.java"],
    visibility = [
        "//src/main/java/com/code_intelligence/jazzer/mutation/mutator/libfuzzer:__pkg__",
        "//src/main/native/com/code_intelligence/jazzer/driver:__pkg__",
    ],
)

java_library(
    name = "runtime",
    srcs = [
        "HardToCatchError.java",
        "JazzerInternal.java",
        "NativeLibHooks.java",
        "TraceCmpHooks.java",
        "TraceDivHooks.java",
        "TraceIndirHooks.java",
    ],
    visibility = [
        "//src/main/java/com/code_intelligence/jazzer/android:__pkg__",
        "//src/main/native/com/code_intelligence/jazzer/driver:__pkg__",
        "//src/test:__subpackages__",
    ],
    runtime_deps = [
        ":fuzz_target_runner_natives",
        ":mutator",
        # Access to Unsafe is possible without any tricks if the class that does it is loaded by the
        # bootstrap loader. We thus want Jazzer to use this class from jazzer_bootstrap.
        "//src/main/java/com/code_intelligence/jazzer/utils:unsafe_provider",
    ],
    deps = [
        ":constants",
        ":coverage_map",
        ":trace_data_flow_native_callbacks",
        "//src/main/java/com/code_intelligence/jazzer/api:hooks",
    ],
)

# This target exposes a class that can safely be loaded in both the system and the bootstrap class
# loader as it provides true constants that do not change over the lifetime of the JVM.
java_library(
    name = "constants",
    srcs = ["Constants.java"],
    visibility = ["//visibility:public"],
)
